package ali;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 *
 * 编写一个程序，开启三个线程，这三个线程的 ID 分别是 A、B 和 C，
 * 每个线程把自己的 ID 在屏幕上打印 10 遍，要求输出结果必须按 ABC 的顺序显示，如 ABCABCABC... 依次递推
 *
 * @author wxh
 */
public class Solution_17 {

	// 先让线程A打印
	private static boolean printB = false;
	private static boolean printC = false;

	public static void main(String[] args) throws InterruptedException {

		Lock lock = new ReentrantLock();
		Condition conditionA = lock.newCondition();
		Condition conditionB = lock.newCondition();
		Condition conditionC = lock.newCondition();

		AtomicInteger countA = new AtomicInteger(0);
		AtomicInteger countB = new AtomicInteger(0);
		AtomicInteger countC = new AtomicInteger(0);

		Thread threadA = new Thread(() -> {
			try {
				lock.lock();

				while (countA.get() < 10) { //只要没有打印完，就一直执行

					System.out.print(Thread.currentThread().getName());
					countA.incrementAndGet();

					//唤醒线程B打印
					printB = true;
					conditionB.signal();

					//结束或进入阻塞等待
					if (countA.get()>= 10) { // 如果打印完10个，直接break，结束线程
						break;
					} else { //如果没有打印完，则阻塞等待线程C唤醒
						conditionA.await();
					}
				}

			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}, "A");

		Thread threadB = new Thread(() -> {
			try {
				lock.lock();

				// 一开始如果为fasle，则阻塞等待别的线程A唤醒
				while (!printB) {
					conditionB.await();
				}

				while (countB.get() < 10) {
					System.out.print(Thread.currentThread().getName());
					countB.incrementAndGet();

					//唤醒线程B打印
					printC = true;
					conditionC.signal();

					//结束或进入阻塞等待
					if (countB.get()>= 10) { // 如果打印完10个，直接break，结束线程
						break;
					} else { //如果没有打印完，则阻塞等待线程A唤醒
						conditionB.await();
					}

				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}, "B");

		Thread threadC = new Thread(() -> {
			try {
				lock.lock();

				// 一开始如果为fasle，则阻塞等待别的线程B唤醒
				while (!printC) {
					conditionC.await();
				}

				while (countC.get() < 10) {
					System.out.print(Thread.currentThread().getName());
					countC.incrementAndGet();

					//唤醒线程A打印
					conditionA.signal();

					//结束或进入阻塞等待
					if (countC.get()>= 10) { // 如果打印完10个，直接break，结束线程
						break;
					} else { //如果没有打印完，则阻塞等待线程B唤醒
						conditionC.await();
					}

				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}, "C");

		threadA.start();
		threadB.start();
		threadC.start();

		// 让三个线程插队到main线程前面执行完后，main线程再继续执行
		threadA.join();
		threadB.join();
		threadC.join();

		// 等三个线程执行完，再
		System.out.println("");
		System.out.println("任务完毕");


	}

}